package com.systop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.systop.dao.GoodsStockDao;
import com.systop.domain.to.QueryStockTo;
import com.systop.domain.vo.GoodsStockVo;
import com.systop.entity.Goods;
import com.systop.entity.GoodsStock;
import com.systop.entity.Order;
import com.systop.entity.StockLockDetail;
import com.systop.exception.NoStockException;
import com.systop.service.GoodsStockService;
import com.systop.service.StockLockDetailService;
import com.systop.utils.NumberMatchUtil;
import com.systop.utils.sql.PageUtils;
import com.systop.utils.sql.Query;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * @Description: TODO
 * @Author: jsj
 * @Date: 2023/2/19
 */
@Service
public class GoodsStockServiceImpl extends ServiceImpl<GoodsStockDao, GoodsStock> implements GoodsStockService {

    @Autowired
    private GoodsStockDao goodsStockDao;

    @Autowired
    private StockLockDetailService stockLockDetailService;

    @Autowired
    AmqpTemplate amqpTemplate;

    //分页查询库存信息
    @Override
    public PageUtils selectStockList(Map<String, Object> params) {
        IPage<GoodsStock> page = this.page(
                new Query<GoodsStock>().getPage(params),
                new QueryWrapper<GoodsStock>()
        );
        return new PageUtils(page);
    }

    @Override
    public PageUtils queryStockList(Map<String, Object> params) {

        Integer greaterStockNum = null;
        Integer lessStockNum = null;

        QueryWrapper<QueryStockTo> wrapper = new QueryWrapper<>();

        if (params.get("greaterStockNum")!=null && params.get("greaterStockNum")!=""
                && NumberMatchUtil.isInteger(params.get("greaterStockNum").toString())) {
            greaterStockNum = Integer.parseInt(params.get("greaterStockNum").toString());
        }

        if (params.get("lessStockNum")!=null && params.get("lessStockNum")!=""
                && NumberMatchUtil.isInteger(params.get("lessStockNum").toString())) {
            lessStockNum = Integer.parseInt(params.get("lessStockNum").toString());
        }


        //获取分页数据
        IPage<QueryStockTo> page = new Query<QueryStockTo>().getPage(params);

        //联合查询出数据
        List<QueryStockTo> stockList = this.baseMapper.queryStockList(page,greaterStockNum,lessStockNum);

        //返回分页后的数据
        return new PageUtils(stockList,(int)page.getTotal(),(int)page.getSize(),(int)page.getCurrent());
    }

    //库存数检查(第一次添加库存使用)
    @Override
    public boolean stockMatch(List<GoodsStockVo> goodsStockVoList){
        //数据类型转换:goodsStockVo转换成goodsStock
        boolean matching = goodsStockVoList.stream().anyMatch(
                item -> item.getStockNum() < 0
        );
        return matching;
    }

    //批量添加库存
    @Override
    public void stockBatchAdd(List<GoodsStock> goodsStockList){
        Integer integer = goodsStockDao.insertBatchSomeColumn(goodsStockList);
    }

    @Override
    public void updateBatchByGoodsId(List<GoodsStock> goodsStockList) {
        Integer integer = goodsStockDao.updateBatchByGoodsId(goodsStockList);
    }

    //库存数检查(判断库存量减去锁定库存是否大于等于0)
    @Override
    public boolean lockStockMatch(GoodsStockVo goodsStockVo,GoodsStock goodsStock) {
        if (goodsStockVo.getStockNum()+goodsStock.getStockNum()-goodsStock.getLockStockNum()<0)
            return false;
        return true;
    }

    //根据商品id查询对应库存信息
    @Override
    public GoodsStock getStockByGoodsId(Long goodsId) {
        return goodsStockDao.getStockByGoodsId(goodsId);
    }

    //判断库存表中是否已经存在商品id (返回已经存在的商品id)
    @Override
    public List<Long> existGoodsIds(List<Long> goodsIds){
        return goodsStockDao.existGoodsIds(goodsIds);
    }

    @Override
    public boolean updateStock(GoodsStockVo goodsStockVo) {
        //根据商品id查询对应库存信息
        GoodsStock goodsStock = this.getStockByGoodsId(goodsStockVo.getGoodsId());

        //库存数检查(判断库存量减去锁定库存是否大于等于0)
        if (goodsStock == null || !this.lockStockMatch(goodsStockVo, goodsStock)) {
            return false;
        }

        CompletableFuture.runAsync(()->{
            GoodsStock updGoodsStock = new GoodsStock();
            BeanUtils.copyProperties(goodsStockVo, updGoodsStock);

            List<GoodsStock> list = new ArrayList<>();
            list.add(updGoodsStock);

            this.updateBatchByGoodsId(list);
        });

        return true;
    }

    /**
     * 锁定库存方法
     * @param orderList
     * @return
     */
    @Override
    public Boolean orderLockStock(List<Order> orderList) {

        Boolean lockedStock = true;

        for(Order order : orderList){
            //成功就返回1，否则就是0
            Long count = baseMapper.lockStock(order.getGoods().getGoodsId(),order.getGoodsNum());
            if (count == 1) {
                //保存库存扣减详情
                StockLockDetail stockLockDetail = new StockLockDetail();
                stockLockDetail.setOrderNo(order.getOrderNo());
                stockLockDetail.setGoodsId(order.getGoodsId());
                stockLockDetail.setGoodsNum(order.getGoodsNum());
                stockLockDetail.setLockStatus(1);
                stockLockDetailService.save(stockLockDetail);
                amqpTemplate.convertAndSend("stock-event-exchange","stock.locked",stockLockDetail);
                continue;
            }else if (count == 0){
                lockedStock = false;
            }
            if(lockedStock){
                throw new NoStockException(order.getGoods().getGoodsId());
            }
        }

        return lockedStock;
    }


    /**
     * 解锁库存方法
     * @param stockLockDetailList
     */
    @Transactional
    @Override
    public void unLockStock(List<StockLockDetail> stockLockDetailList){
        System.out.println("开始解锁库存，订单号:"+stockLockDetailList.get(0).getOrderNo());
        String orderNo = stockLockDetailList.get(0).getOrderNo();
        for (StockLockDetail stockLockDetail : stockLockDetailList) {
            if (stockLockDetail.getLockStatus() == 1) {
                System.out.println("执行解锁库存方法,解锁的库存id:"+stockLockDetail.getGoodsId());
                this.update(new UpdateWrapper<GoodsStock>()
                        .eq("goods_id", stockLockDetail.getGoodsId())
                        .setSql("lock_stock_num = lock_stock_num - " + stockLockDetail.getGoodsNum()));
            }
        }
        stockLockDetailService.update(new UpdateWrapper<StockLockDetail>().eq("order_no", orderNo)
                .set("lock_status", 2));
    }
}

